Mybatis 您所在的位置:网站首页 mybatisplus limit语法 Mybatis

Mybatis

2023-12-25 04:30| 来源: 网络整理| 查看: 265

有道无术,术尚可求,有术无道,止于术。

文章目录 前言方案分析1. 分页2. XML自定义SQL 案例演示1. 配置2. 简单分页查询3. 带方言的分页查询 参考

前言

在我们实际开发软件产品过程中,数据库的类型可能不是确定的,也有客户会有要求必须用什么数据库,比如很多政府机构要求必须使用国产数据库,所以我们在开发时,需要适配多种数据库。

MySQL、Oracle、PostgreSQL、达梦等数据库在进行增删改查时,都是基于美国国家标准局制定的SQL标准,比如SQL-92、SQL-99。

但是每个数据库厂商实际的SQL会有较小差异,也就是数据库方言,大家最熟知的就是MySQL分页使用limit,Oracle分页使用rownum。

MyBatis-Plus支持各种标准 SQL 的数据库,接下来我们实际演示如何使用MyBatis-Plus适配各种数据库。 在这里插入图片描述

方案分析 1. 分页

很多数据库分页SQL使用方式都不大相同,MyBatis-Plus内置分页插件PaginationInnerInterceptor已支持多种数据库,官网说明: 在这里插入图片描述

在使用内置分页插件时,可以设置数据库的类型:

@Configuration @MapperScan("com.pearl.pay.mapper") //持久层扫描 @EnableTransactionManagement //启用事务管理 public class MybatisPlusConfig { @Bean @ConditionalOnMissingBean(MybatisPlusInterceptor.class) public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(); paginationInnerInterceptor.setDbType(DbType.MYSQL); interceptor.addInnerInterceptor(paginationInnerInterceptor); return interceptor; } }

内置分页插件在执行SQL时,会根据当前数据库类型获取分页方言。 在这里插入图片描述 在分页方言工厂类DialectFactory中,可以看到具体获取方言逻辑,mysql、mariadb、clickhouse、oceanbase等数据库都是使用mysql方言。 在这里插入图片描述 oracle、达梦数据库用的是oracle方言: 在这里插入图片描述 MYSQL 数据库分页语句使用LIMIT组装: 在这里插入图片描述 ORACLE 数据库分页语句使用ROWNUM、ROW_ID组装: 在这里插入图片描述 综上: 在分页时,适配多种数据库只需要在分页插件中设置数据库类型即可。

2. XML自定义SQL

调用MP的API进行增删改查时,比如调用xxMpper.selectList()时,因为MP在构建SQL时,都是使用的基础标准,所以一般不存在兼容问题。但是我们自己在XML文件中编写SQL,就需要注意各种数据库匹配兼容问题了。

Mybatis本身已经做了多数据库支持,只需要告诉框架用的是什么数据库,可以根据不同的数据库厂商执行不同的语句。

Mybatis中的DatabaseIdProvider (数据库厂商标识提供者)接口声明了获取厂商标识的方法,标识可用于以后为每种数据库类型构建不同的查询,该机制支持多个厂商或版本。

public interface DatabaseIdProvider { default void setProperties(Properties p) { // NOP } // 根据数据源获取数据库厂商标识 String getDatabaseId(DataSource dataSource) throws SQLException; }

Mybatis也提供了VendorDatabaseIdProvider实现类:

public class VendorDatabaseIdProvider implements DatabaseIdProvider { // 支持的数据库厂商(需要自己定义),比如: Oracle=》oracle private Properties properties; // 获取数据库厂商标识ID(databaseId),eg:oracle @Override public String getDatabaseId(DataSource dataSource) { if (dataSource == null) { throw new NullPointerException("dataSource cannot be null"); } try { return getDatabaseName(dataSource); } catch (Exception e) { LogHolder.log.error("Could not get a databaseId from dataSource", e); } return null; } @Override public void setProperties(Properties p) { this.properties = p; } // 根据产品名称,获取对应的databaseId。 private String getDatabaseName(DataSource dataSource) throws SQLException { String productName = getDatabaseProductName(dataSource); if (this.properties != null) { for (Map.Entry property : properties.entrySet()) { if (productName.contains((String) property.getKey())) { return (String) property.getValue(); } } // no match, return null return null; } return productName; } // 从数据源中获取数据库产品名称,比如: Oracle private String getDatabaseProductName(DataSource dataSource) throws SQLException { try (Connection con = dataSource.getConnection()) { DatabaseMetaData metaData = con.getMetaData(); return metaData.getDatabaseProductName(); } } }

在Mybatis的XML中编写SQL时,有个databaseId属性,可以指定当前语句块属于哪个数据库类型,比如:

select * from user where user_id = #{id}

综上:我们只需要配置DatabaseIdProvider 中支持哪些数据库,然后在XML中针对每种数据库方言编写查询语句,并添加databaseId属性,Mybatis会在启动时获取数据源使用的哪个类型数据库,然后执行配置了当前数据库对应的语句

案例演示 1. 配置

搭建工程,集成MP、Oracle、Mysql很简单,这里就不赘述了。

在配置文件中,添加对应的Oracle、Mysql连接地址:

spring: datasource: type: com.zaxxer.hikari.HikariDataSource driver-class-name: oracle.jdbc.OracleDriver url: jdbc:oracle:thin:@127.0.0.1:1521:ORCL username: root password: root #driver-class-name: com.mysql.cj.jdbc.Driver #url: jdbc:mysql://127.0.0.1:3306/d_account?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai #username: root #password: root

在MP中添加配置类:

@Configuration @MapperScan("com.pearl.pay.mapper") //持久层扫描 @EnableTransactionManagement //启用事务管理 public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor(DataSource dataSource,DatabaseIdProvider databaseIdProvider) throws SQLException { // MP插件 MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(); // 获取当前数据源对应的数据库类型,添加分页插件 String databaseId = databaseIdProvider.getDatabaseId(dataSource); DbType dbType = DbType.getDbType(databaseId); paginationInnerInterceptor.setDbType(dbType); interceptor.addInnerInterceptor(paginationInnerInterceptor); return interceptor; } @Bean public DatabaseIdProvider databaseIdProvider() { // 数据库厂商提供者 DatabaseIdProvider databaseIdProvider = new VendorDatabaseIdProvider(); Properties p = new Properties(); p.setProperty("Oracle", "oracle"); p.setProperty("Mysql", "mysql"); databaseIdProvider.setProperties(p); return databaseIdProvider; } } 2. 简单分页查询

因为MyBatis-Plus内置分页插件已经做了适配,简单的(没有数据库方言)分页查询不用自己写代码适配。

首先添加一个分页查询:

IPage test(Page page); select * from user

数据源配置的是Oracle,没有配置databaseId,测试SQL语句打印如下:

SELECT * FROM ( SELECT TMP.*, ROWNUM ROW_ID FROM ( select * from user) TMP WHERE ROWNUM 0

数据源配置为Mysql,测试SQL语句打印如下:

select * from user LIMIT 10 3. 带方言的分页查询

需求: 查询时间节点小于当前时间的数据。

Oracle当前时间使用的是sysdate函数,Mysql使用的是now()函数,这个时候就需要手动去兼容了。

编写两个重名的查询语句,针对不同的数据库厂商编写SQL,并配置对应的databaseId

select * from user t select * from user t

也可以使用if语句,判断当前数据库类型,添加不同语句(推荐)。

select * from user t

切换数据库,执行如下:

select * from user t where t.create_time


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有